/*
 *	PROGRAM:	Language Preprocessor
 *	MODULE:		gpre.h
 *	DESCRIPTION:	Common header modules
 *
 * The contents of this file are subject to the Interbase Public
 * License Version 1.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy
 * of the License at http://www.Inprise.com/IPL.html
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code was created by Inprise Corporation
 * and its predecessors. Portions created by Inprise Corporation are
 * Copyright (C) Inprise Corporation.
 *
 * All Rights Reserved.
 * Contributor(s): ______________________________________.
 *
 * Revision 1.3  2000/11/27 09:26:13  fsg
 * Fixed bugs in gpre to handle PYXIS forms
 * and allow edit.e and fred.e to go through
 * gpre without errors (and correct result).
 *
 * This is a partial fix until all
 * PYXIS datatypes are adjusted in frm_trn.c
 *
 * removed some compiler warnings too
 *
 * Revision 1.2  2000/11/16 15:54:29  fsg
 * Added new switch -verbose to gpre that will dump
 * parsed lines to stderr
 *
 * Fixed gpre bug in handling row names in WHERE clauses
 * that are reserved words now (DATE etc)
 * (this caused gpre to dump core when parsing tan.e)
 *
 * Fixed gpre bug in handling lower case table aliases
 * in WHERE clauses for sql dialect 2 and 3.
 * (cause a core dump in a test case from C.R. Zamana)
 *
 * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports:
 *                         - "IMP" and "HP9000 s300"
 *
 * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "UNIXWARE" port
 * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "Ultrix" port
 *
 * 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port
 * 2002.10.28 Sean Leyne - Completed removal of obsolete "SGI" port
 * 2002.10.28 Sean Leyne - Completed removal of obsolete "HP700" port
 *
 * 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
 *
 * Stephen W. Boyd       - Added support for new features.
*/

#ifndef GPRE_GPRE_H
#define GPRE_GPRE_H

#include <stddef.h>				// offsetof

#include <stdio.h>
#include "dyn_consts.h"
#include "ibase.h"
#include "../jrd/constants.h"
#include "../common/utils_proto.h"

#ifdef GPRE_FORTRAN
#if defined AIX || defined AIX_PPC || defined __sun
#define FTN_BLK_DATA
#endif
#endif


static const char* const CONST_STR	= "const ";


const int MAX_SYM_SIZE		= 512;		// max length of symbol + terminator
const int NAME_SIZE 	= 32;
const int MAX_CURSOR_SIZE = 64;
const int MAX_REF_SIZE = 32; // references are generated by gpre
const int ERROR_LENGTH	= 256;
const int MAX_DATABASES = 32;
const int MAX_EVENT_SIZE = 16; // event names use 15 chars from old docs.

// Values for SQL dialects.
#include "firebird/impl/sqlda_pub.h"

// Language options

enum lang_t
{
	lang_undef,
	lang_internal,
	lang_pascal,
	lang_fortran,
	lang_cobol,
	lang_c,
	lang_ada,
	lang_cxx,
	lang_scxx,
	lang_cplusplus,
	lang_cpp,
	lang_internal_cxx
};

#ifdef GPRE_COBOL
// Cobol dialect options
enum cob_t
{
	cob_vms,					// VMS
	cob_ansi,					// ANSI-85
	cob_rmc						// RM/Cobol
};
#endif


//___________________________________________________________________
// Test if input language is cpp based.
//
// The lang_internal is used to compile some internal stuff without
// reference to a database.  Previously it was based on lang_c (but even then
// if you look carefully there are some areas where lang_c is specifically
// treated and lang_internal would be ignored).
// Now the base language used for lang_internal is cpp, so we have this
// inline function to tell if language is cpp.
// Internally the sw_language variable is set to lang_cxx for the
// c++ source files, cxx, cpp, cplusplus, so we only need to test lang_cxx
// and lang_internal.
//

bool isLangCpp(lang_t lang);

#ifdef GPRE_COBOL
bool isAnsiCobol(cob_t dialect);
#endif


// Structure used by Fortran to determine whether or not
// an array has been declared in a subroutine.

#ifdef GPRE_FORTRAN
struct adl
{
	ULONG adl_gds_ident;		// Identifier of array for which Gpre has
								// generated a declaration in main or a subroutine
	adl* adl_next;				// Next declared array identifier
};

const size_t ADL_LEN = sizeof(adl);


// database block data, for generating block data section in fussy fortran

struct dbd
{
	enum {dbd_size = 128};
	TEXT dbd_name[dbd_size];			// database name
};
#endif


// Dimension block, used for arrays
// Note: this structure is being phased out.  Please use the
// repeating tail on the ARY structure instead

struct dim
{
	int dim_number;				// Dimension number i (i=1 to n)
	SLONG dim_lower;			// Lower bound
	SLONG dim_upper;			// Upper bound
	dim* dim_next;				// Information for dimension i+1
	dim* dim_previous;			// Information for dimension i-1
};

const size_t DIM_LEN = sizeof(dim);


struct gpre_file
{
	SLONG fil_length;			// File length in pages
	SLONG fil_start;			// Starting page
	TEXT *fil_name;				// File name
	gpre_file* fil_next;		// next file
	USHORT fil_shadow_number;	// shadow number if part of shadow
	USHORT fil_flags;
};

enum fil_flags_vals {
	FIL_manual	= 1,	// Manual shadow
	//FIL_raw		= 2,	// On raw device; unused
	FIL_conditional	= 4	// Conditional shadow
};

const size_t FIL_LEN = sizeof(gpre_file);


// filter block

struct gpre_filter
{
	TEXT *fltr_name;
	const TEXT *fltr_entry_point;
	const TEXT *fltr_module_name;
	SSHORT fltr_input_type;
	SSHORT fltr_output_type;
};

const size_t FLTR_LEN = sizeof(gpre_filter);


// General Syntax node, produced by parser
// CVC: several node types are unused!!!

enum nod_t {
	nod_nothing = 0,
	nod_field = 1, nod_literal, nod_value,
	nod_and, nod_or, nod_not,
	nod_eq, nod_equiv, nod_ne, nod_ge,
	nod_le, nod_gt, nod_lt,
	nod_containing, nod_matches, nod_any,
	nod_unique, nod_plus, nod_times,
	nod_divide, nod_minus, nod_negate,
	//nod_msg,
	//nod_for,
	//nod_send,
	//nod_receive,
	//nod_block,
	//nod_select,
	//nod_boolean,
	nod_projection,
	nod_sort,
	nod_store, nod_modify, nod_erase,
	//nod_if,
	nod_assignment,
	//nod_rse,
	//nod_first,
	//nod_relation,
	//nod_end,
	//nod_label,
	//nod_leave,
	//nod_loop,
	nod_max, nod_min, nod_count,
	nod_total, nod_average, nod_list,
	nod_deferred, nod_missing, nod_between,
	nod_union,
	//nod_map,
	nod_starting,
	nod_like, nod_agg_count, nod_agg_max,
	nod_agg_min, nod_agg_total, nod_agg_average,
	nod_aggregate, nod_from, nod_null,
	nod_asterisk, nod_map_ref, nod_user_name,
	nod_upcase, nod_sleuth, nod_event_init,
	nod_udf, nod_array, nod_index,
	nod_via, nod_join_inner, nod_join_left,
	nod_join_right, nod_join_full, nod_join,
	nod_concatenate, nod_cast, nod_dom_value,
	nod_ansi_any, nod_gen_id,
	//nod_set_generator,
	nod_merge, nod_plan_expr, nod_plan_item,
	nod_natural, nod_index_order, nod_ansi_all,
	nod_extract, nod_current_date,
	nod_current_time, nod_current_timestamp,
	nod_lowcase, nod_nullif, nod_current_connection,
	nod_current_role, nod_current_transaction,
	nod_coalesce, nod_case, nod_case1,
	nod_substring,
	nod_LASTNOD					// Leave this debugging gpre_nod last
};

struct gpre_nod
{
	nod_t nod_type;				// node type
	USHORT nod_count;			// number of sub-items
	gpre_nod* nod_arg[1];		// argument
};

inline FB_SIZE_T NOD_LEN(const FB_SIZE_T cnt)
{
	return sizeof(gpre_nod) + (cnt ? cnt - 1 : 0) * sizeof(gpre_nod*);
}


struct set_dialect
{
	USHORT sdt_dialect;			// Dialect  value as specified by SET stmt
};

const size_t SDT_LEN = sizeof(set_dialect);


// Set generator block

struct set_gen
{
	TEXT* sgen_name;
	USHORT sgen_dialect;
	SLONG sgen_value;
	SINT64 sgen_int64value;
};

const size_t SGEN_LEN = sizeof(set_gen);


// STRing block - holds a null terminated string

typedef struct str {
	TEXT str_string[1];			// pretty simple, no?
} *STR;

inline size_t STR_LEN(const size_t size)
{
	return sizeof(str) + size;
}


// SQL WHENEVER BLOCK

enum swe_condition_vals {
	SWE_error,
	SWE_warning,
	SWE_not_found,
	SWE_max
};

struct swe
{
	swe*				swe_next;			// Next in chain
	swe_condition_vals	swe_condition;		// Condition
	USHORT				swe_length;			// Length of label
	TEXT				swe_label[1];		// Label
};


// Text block

struct gpre_txt
{
	ULONG txt_position;
	USHORT txt_length;
};

const size_t TXT_LEN = sizeof(gpre_txt);


// User name -- used for SQL GRANT/REVOKE

struct gpre_usn
{
	gpre_usn*		usn_next;
	const SCHAR*	usn_name;
	USHORT			usn_dyn;	// describes the type of user via a dyn-verb,
								// i.e. gds__dyn_grant_user/view/proc/trig
};

const size_t USN_LEN = sizeof(gpre_usn);


// value block, used to store a set of values

struct gpre_value
{
	gpre_value* val_next;			// next value in list
	const TEXT* val_value;			// value
};

const size_t VAL_LEN = sizeof(gpre_value);


// Array information block.  Used to hold info about an array field.
// Note: the dimension (dim) block used to hold dimension information.
// The preferred mechanism is the repeating tail on the array block.

struct ary
{
	USHORT ary_dtype;			// data type of array
	int ary_dimension_count;	// Number of dimensions in this array
	dim* ary_dimension;			// Linked list of range info for each dimension
	SLONG ary_size;				// Size of the array
	ULONG ary_ident;			// Array identifier
	bool ary_declared;			// True if a declaration already was generated
	struct ary_repeat
	{
		SLONG ary_lower;
		SLONG ary_upper;
	} ary_rpt[MAX_ARRAY_DIMENSIONS];
};

// CVC: The count is ignored, the array is hardcoded at 16.
const size_t ARY_LEN = sizeof(ary);



// Trigger block
// Note: This structure will need expansion later.  Currently its
// use is to create a trigger for CHECK constraints which always
// abort on error

struct gpre_trg
{
	//str* trg_name;			// unused
	USHORT trg_type;			// Type of trigger
	str* trg_source;			// source for trigger
	gpre_nod* trg_boolean;		// boolean expression, for trigger
	str* trg_message;			// Message the trigger prints
};

const size_t TRG_LEN = sizeof(gpre_trg);


// Linked list stack stuff

struct gpre_lls {
	gpre_nod* lls_object;		// object on stack
	gpre_lls* lls_next;			// next item on stack
};

const size_t LLS_LEN = sizeof(gpre_lls);


// Constraint block, used to hold information about integrity constraints

struct cnstrt
{
	str* cnstrt_name;					// Name of constraint
	USHORT cnstrt_type;					// Type of constraint
	gpre_lls* cnstrt_fields;			// list of fields
	USHORT cnstrt_fkey_def_type;		// extended foreign key definition
	str* cnstrt_referred_rel;			// referred relation, if foreign key
	gpre_lls* cnstrt_referred_fields;	// optional list of fields from referred relation
	cnstrt* cnstrt_next;				// next contraint for field or relation
	gpre_txt* cnstrt_text;				// source for CHECK constraints
	gpre_nod* cnstrt_boolean;			// boolean expression, for CHECK constraints
	USHORT cnstrt_flags;				// see below
};

const size_t CNSTRT_LEN = sizeof(cnstrt);

// Values for cnstrt_fkey_def_type

enum cnstrt_fkey_def_type_vals {
	REF_UPDATE_ACTION	= 0x0001,
	REF_UPD_CASCADE		= 0x0002,
	REF_UPD_SET_DEFAULT	= 0x0004,
	REF_UPD_SET_NULL	= 0x0008,
	REF_UPD_NONE		= 0x0010,
	REF_UPDATE_MASK		= 0x001E,

	REF_DELETE_ACTION	= 0x0020,
	REF_DEL_CASCADE		= 0x0040,
	REF_DEL_SET_DEFAULT	= 0x0080,
	REF_DEL_SET_NULL	= 0x0100,
	REF_DEL_NONE		= 0x0200,
	REF_DELETE_MASK		= 0x03C0
};

// Values for cnstrt_type

enum cnstrt_type_vals {
	CNSTRT_NOT_NULL = 1,
	CNSTRT_PRIMARY_KEY,
	CNSTRT_UNIQUE,
	CNSTRT_FOREIGN_KEY,
	CNSTRT_CHECK
};

// Values for cnstrt_flags

enum cnstrt_flags_vals {
	//CNSTRT_DEFERRABLE			= 1,
	//CNSTRT_INITIALLY_DEFERRED	= 2,
	CNSTRT_delete				= 4
};


// Grant/revoke block

typedef struct prv
{
	USHORT prv_privileges;		// holds privileges being granted or revoked
	const SCHAR* prv_username;	// user having privileges granted or revoked
	USHORT prv_user_dyn;		// the dyn-verb to be used with prv_username
								// i.e. gds__dyn_grant_user/proc/trig/view
	str* prv_relation;			// relation on which we're doing grant/revoke
	USHORT prv_object_dyn;		// the dyn-verb to be used with prv_relation
								// i.e. gds__dyn_rel/proc_name
	gpre_lls* prv_fields;		// fields on which we're doing grant/revoke
	prv* prv_next;				// next grant/revoke block (with different user)
} *PRV;

const size_t PRV_LEN = sizeof(prv);

enum priv_types
{
	PRV_no_privs	= 0,		// no privileges being granted or revoked
	PRV_select		= 1,		// select privilege being granted or revoked
	PRV_insert		= 2,		// insert privilege being granted or revoked
	PRV_delete		= 4,		// delete privilege being granted or revoked
	PRV_update		= 8,		// update privilege being granted or revoked
	PRV_execute		= 16,		// execute privilege being granted or revoked
	PRV_references	= 32,		// reference privilege
	PRV_grant_option= 64,		// privilege to grant privileges being granted
	PRV_all			= 128		// all privileges being granted/revoked
};


// statistic block. Used for all statistics commands

typedef struct sts
{
	str* sts_name;				// object name
	USHORT sts_flags;			// Miscellaneous flags
} *STS;

const size_t STS_LEN = sizeof(sts);
enum sts_flags_vals {
	STS_index = 1		// Object is an index
};


// Computed field block

typedef struct cmpf {
	gpre_txt* cmpf_text;		// source for computed field
	gpre_nod* cmpf_boolean;		// expression, for computed field
} *CMPF;

const size_t CMPF_LEN = sizeof(cmpf);

// ***************** end of tree top **********************


// Forward declarations

struct gpre_ctx;
struct gpre_fld;
struct gpre_rel;
class gpre_req;
class ref;

enum act_t {
	ACT_any,
	ACT_alter_database,
	ACT_alter_domain,
	ACT_alter_index,
	ACT_alter_table,
	ACT_at_end,
	//ACT_average,
	ACT_b_declare,
	ACT_basedon,
	ACT_blob_cancel,
	ACT_blob_close,
	ACT_blob_create,
	ACT_blob_for,
	ACT_blob_handle,
	ACT_blob_open,
	//ACT_block_data,
	ACT_close,
	ACT_commit,
	ACT_commit_retain_context,
	ACT_create_database,
	ACT_create_domain,
	ACT_create_generator,
	ACT_create_index,
	ACT_create_shadow,
	ACT_create_table,
	ACT_create_view,
	ACT_cursor,
	ACT_database,
	ACT_declare_filter,
	ACT_declare_udf,
	//ACT_delete,
	ACT_disconnect,
	ACT_drop_database,
	ACT_drop_domain,
	ACT_drop_filter,
	ACT_drop_index,
	ACT_drop_shadow,
	ACT_drop_table,
	ACT_drop_udf,
	ACT_drop_view,

	ACT_dyn_close,
	ACT_dyn_cursor,
	//ACT_dyn_declare,
	ACT_dyn_describe,
	ACT_dyn_describe_input,
	ACT_dyn_execute,
	ACT_dyn_fetch,
	ACT_dyn_grant,
	ACT_dyn_immediate,
	ACT_dyn_insert,
	ACT_dyn_open,
	ACT_dyn_prepare,
	ACT_dyn_revoke,
	ACT_dyn_statement,

	ACT_endblob,
	ACT_e_declare,
	ACT_enderror,
	ACT_endfor,
	ACT_endmodify,
	ACT_endstore,
	ACT_endstore_special,
	ACT_erase,
	ACT_event_init,
	ACT_event_wait,
	ACT_fetch,
	ACT_finish,
	ACT_function,
	ACT_for,
	ACT_get_segment,
	ACT_hctef,
	ACT_insert,
	ACT_loop,
	//ACT_max,
	//ACT_min,
	ACT_modify,
	ACT_on_error,
	ACT_open,
	ACT_prepare,
	ACT_procedure,
	ACT_put_segment,
	ACT_ready,
	ACT_release,
	ACT_rfinish,
	ACT_rollback,
	ACT_rollback_retain_context,
	ACT_routine,
	ACT_segment,
	ACT_segment_length,
	ACT_s_end,
	ACT_s_fetch,
	ACT_s_start,
	ACT_select,
	ACT_start,
	ACT_statistics,
	ACT_store,
	ACT_store2,
	//ACT_total,
	ACT_update,
	ACT_variable,
	ACT_clear_handles,
	ACT_type_number,  // let's avoid confusion with act.act_type
	ACT_noop,
	ACT_get_slice,
	ACT_put_slice,
	ACT_sql_dialect,

	ACT_LASTACT					// leave this debugging ACT last
};

// Action block, used to make action points in source

struct act {
	SLONG act_position;			// position in input stream
	SLONG act_length;			// length to be commented out
	act_t act_type;				// type of action
	act* act_next;				// next action in request
	act* act_rest;				// remaining actions in module
	act* act_error;				// on-error action (maybe)
	act* act_pair;				// begin/end action (maybe)
	gpre_req* act_request;		// parent request
	ref* act_object;			// dependent on action type
	swe* act_whenever;			// SQL whenever blocks
	USHORT act_flags;			// flags that affect the action
	USHORT act_count;			// used to hold begin/end count for routines
};

enum act_flags_vals {
	ACT_mark	= 1,		// action is mark only - no comment
	ACT_first	= 2,		// action is first on line.  No FTN continuation
	ACT_break	= 4,		// module boundary break
	ACT_sql		= 8,		// action is SQL statement
	ACT_decl	= 16,		// action is a PASCAL forward or extern routine
	ACT_main	= 32,		// action is the main routine in the program/module
	ACT_back_token	= 128	// end of action marked by prior token
};

const size_t ACT_LEN = sizeof(act);


// Symbol block, also used for hash table

enum sym_t {
	SYM_keyword,
	SYM_context,
	SYM_database,
	SYM_relation,
	SYM_field,
	SYM_variable, // it's tested in sql.cpp but it's never activated
	SYM_stream,
	SYM_cursor,
	SYM_delimited_cursor,
	SYM_index,
	SYM_blob,
	//SYM_statement,
	SYM_dyn_cursor,
	SYM_type,
	SYM_udf,
	SYM_username,
	SYM_procedure,
	SYM_charset,
	SYM_collate,
	SYM_generator,
	SYM_dummy,

	SYM_LASTSYM					// Leave this debugging sym last
};

struct gpre_sym {
	const char* sym_string;		// address of asciz string
	sym_t sym_type;				// symbol type
	USHORT sym_keyword;			// keyword number, if keyword
	gpre_ctx* sym_object;		// general pointer to object
	gpre_sym* sym_collision;	// collision pointer
	gpre_sym* sym_homonym;		// homonym pointer
	SCHAR sym_name[1];			// space for name, if necessary
};

const size_t SYM_LEN = sizeof(gpre_sym);


// Blob block.  Used for blob calls

class blb
{
public:
	gpre_req* blb_request;		// parent request
	blb* blb_next;				// next blob in request
	ref* blb_reference;			// field reference for blob field
	gpre_sym* blb_symbol;		// Blob context variable
	ULONG blb_ident;			// Blob handle
	ULONG blb_buff_ident;		// Ident of segment buffer
	ULONG blb_len_ident;		// Ident of segment length
	ULONG blb_seg_length;		// Segment length of blob
	USHORT blb_flags;			// Misc and various blobs
#ifdef GPRE_FORTRAN
	USHORT blb_top_label;		// fortran label for top of request
	USHORT blb_btm_label;		// fortran label for request exit
#endif
	USHORT blb_bpb_length;		// Length of blob parameter block
	USHORT blb_bpb_ident;		// Ident for blob parameter block
	USHORT blb_type;			// Blob type (0 = default segmented)
	SSHORT blb_const_from_type;
	// Constant value for subtype from which this blob is to be filtered
	//TEXT *blb_var_from_type;
	// Variable whose value is the subtype from which this blob is to be filtered
	SSHORT blb_const_to_type;
	// Constant value for subtype to which this blob is to be filtered
	//TEXT *blb_var_to_type;
	// Variable whose value is the subtype to which this blob is to be filtered
	USHORT blb_from_charset;	// charset to translate from
	USHORT blb_to_charset;		// charset to translate to
	UCHAR blb_bpb[24];
};

const size_t BLB_LEN = sizeof(blb);

enum blb_flags_vals {
	//BLB_create	= 1,	// unused
	BLB_symbol_released	= 2
};


// Reserved relation lock block

struct rrl
{
	rrl* rrl_next;				// next locked relation
	UCHAR rrl_lock_level;		// lock level (SHARE, PROT, EXC
	UCHAR rrl_lock_mode;		// lock mode (READ/WRITE)
	gpre_rel* rrl_relation;		// relation block
};

const size_t RRL_LEN = sizeof(rrl);

// forward declarations
struct tpb;
struct gpre_prc;

// Database block, more or less the granddaddy

struct gpre_dbb
{
	gpre_dbb* dbb_next;				// next database in program
	gpre_rel* dbb_relations;		// relations in database
	gpre_prc* dbb_procedures;		// procedures in database
#ifdef GPRE_COBOL
	USHORT dbb_id;					// database id in program
#endif
	USHORT dbb_flags;				// Misc flag bytes
	gpre_sym* dbb_name;				// database name
	FB_API_HANDLE dbb_handle;		// OUR db handle
	FB_API_HANDLE dbb_transaction;	// default transaction
	rrl* dbb_rrls;					// temporary list of relation locks
	const tpb* dbb_tpbs;			// real tpbs for this db
	const TEXT* dbb_filename;
	const TEXT* dbb_runtime;
	const TEXT* dbb_c_user;			// compiletime user name
	const TEXT* dbb_c_password;		// compiletime password
	const TEXT* dbb_c_sql_role;		// compiletime SQL role
	const TEXT* dbb_r_user;			// runtime user name
	const TEXT* dbb_r_password;		// runtime password
	const TEXT* dbb_r_sql_role;		// runtime SQL role
	const TEXT* dbb_c_lc_messages;	// compiletime user natural language
	const TEXT* dbb_c_lc_ctype;		// compiletime user character set
	const TEXT* dbb_r_lc_messages;	// runtime user natural language
	const TEXT* dbb_r_lc_ctype;		// runtime user character set
	const TEXT* dbb_def_charset;	// charset for CREATE DATABASE
	SSHORT dbb_know_subtype;		// Use a charset subtype id on messages
	SSHORT dbb_char_subtype;		// subtype to use for all SCHAR messages
	FB_API_HANDLE dbb_field_request;
	FB_API_HANDLE dbb_flds_request;
	//FB_API_HANDLE dbb_relation_request;
	FB_API_HANDLE dbb_procedure_request;
	FB_API_HANDLE dbb_udf_request;
	FB_API_HANDLE dbb_trigger_request;
	FB_API_HANDLE dbb_proc_prms_request;
	FB_API_HANDLE dbb_proc_prm_fld_request;
	FB_API_HANDLE dbb_index_request;
	FB_API_HANDLE dbb_type_request;
	FB_API_HANDLE dbb_array_request;
	FB_API_HANDLE dbb_dimension_request;
	FB_API_HANDLE dbb_domain_request;
	//FB_API_HANDLE dbb_generator_request;
	FB_API_HANDLE dbb_view_request;
	FB_API_HANDLE dbb_primary_key_request;
	int dbb_scope;					// scope of the database handle
#ifdef NOT_USED_OR_REPLACED
	int dbb_allocation;
#endif
	int dbb_pagesize;
	int dbb_buffercount;
	ULONG dbb_length;				// Length of database in pages, if known
	gpre_file* dbb_logfiles;
	gpre_file* dbb_files;
};

const size_t DBB_LEN = sizeof(gpre_dbb);

enum dbb_flags_valss {
	//DBB_no_arrays	= 1,		// Obsolete: used for databases before IB4
	DBB_sqlca		= 2,		// Created as default for a sqlca
	DBB_in_trans	= 4,		// included in this transaction
//	DBB_drop_log	= 8,
	DBB_log_serial	= 16
//	DBB_cascade		= 64,		// only set but not used
};

enum dbb_scope_vals {
	//DBB_GLOBAL,
	DBB_EXTERN = 1,
	DBB_STATIC
};

// TPB block

struct tpb {
	tpb* tpb_tra_next;			// next TPB for this transaction
	const tpb* tpb_dbb_next;	// next TPB for this database
	gpre_dbb* tpb_database;		// gpre_dbb of this part of the transaction
	USHORT tpb_length;			// length of actual TPB
	ULONG tpb_ident;			// unique part of name for this TPB
	UCHAR tpb_string[1];		// actual TPB
};

inline FB_SIZE_T TPB_LEN(const FB_SIZE_T tpb_string_len)
{
	return sizeof(tpb) + tpb_string_len;
}


// Procedure structure

struct gpre_prc
{
	gpre_sym* prc_symbol;		// symbol for relation
	SSHORT prc_id;				// procedure id
	gpre_sym* prc_owner;		// owner of procedure, if any
	gpre_dbb* prc_database;		// parent database
	gpre_prc* prc_next;			// next procedure in database, a linked list is created with
								// head in database->dbb_procedures, but never used
	gpre_fld* prc_inputs;		// linked list of input parameters
	gpre_fld* prc_outputs;		// linked list of output parameters
	SSHORT prc_in_count;		// count of input parameters
	SSHORT prc_out_count;		// count of output parameters
	SSHORT prc_flags;			// procedure flags
};

const size_t PRC_LEN = sizeof(gpre_prc);
enum prc_flags_vals {
	PRC_scanned = 1
};


// Maps used by union and global aggregates

struct mel
{
	mel* mel_next;				// Next element in map
	gpre_nod* mel_expr;			// Expression
	//ref* mel_reference;		// unused
	gpre_ctx* mel_context;
	USHORT mel_position;		// Position in map
};

struct map
{
	gpre_ctx* map_context;		// Pseudo context for map
	mel* map_elements;			// Map elements
	USHORT map_count;			// Number of things in map
};


// Record selection expresion syntax node

struct gpre_rse
{
	//USHORT rse_type;			// node type, UNUSED
	gpre_nod* rse_boolean;		// boolean expression, if present
	gpre_nod* rse_first;		// "first n" clause, if present
	gpre_nod* rse_sqlfirst;		// SQL "first n" clause if present
	gpre_nod* rse_sqlskip;		// SQL "skip n" clause if present
	gpre_nod* rse_reduced;		// projection clause, if present
	gpre_nod* rse_sort;			// sort clause, if present
	gpre_nod* rse_fields;		// list of fields
	gpre_nod* rse_into;			// list of output variables
	gpre_nod* rse_union;		// if union, list of sub-rses
	gpre_nod* rse_group_by;		// list of grouping fields
	gpre_nod* rse_plan;			// user-specified access plan
	map* rse_map;				// map for aggregates
	gpre_rse* rse_aggregate;	// Aggregate rse
	nod_t rse_join_type;		// Join type
	USHORT rse_flags;			// flags
	USHORT rse_count;			// number of relations
	gpre_ctx* rse_context[1];	// context block
};


inline FB_SIZE_T RSE_LEN(const FB_SIZE_T cnt)
{
	return sizeof(gpre_rse) + (cnt ? cnt - 1 : 0) * sizeof (int*);
	// CVC: The statement below avoids problem with cnt==0 but at the
	// cost of a possible run-time memory error.
	//return offsetof(gpre_rse, rse_context) + nItems * sizeof(int*);
}

enum rse_flags_vals {
	RSE_singleton = 1,
	RSE_for_update = 2,
	RSE_with_lock = 4
};


// Relation block, not to be confused with siblings or in-laws

struct gpre_rel
{
	USHORT rel_id;				// relation id
	gpre_fld* rel_fields;		// linked list of known fields
	gpre_fld* rel_dbkey;		// linked list of known fields
	gpre_sym* rel_symbol;		// symbol for relation
	gpre_dbb* rel_database;		// parent database
	gpre_rel* rel_next;			// next relation in database
	bool rel_meta;				// if true, created for a metadata operation
	gpre_rse* rel_view_rse;
	gpre_txt* rel_view_text;	// source for VIEW definition
	gpre_sym* rel_owner;		// owner of relation, if any
	cnstrt* rel_constraints;	// linked list of constraints defined during a meta operation
	TEXT *rel_ext_file;			// external file name
	USHORT rel_flags;
};

const size_t REL_LEN = sizeof(gpre_rel);

enum rel_flags_vals {
	REL_view_check	= 1		// View created with check option
};


// Index block. Used for DDL INDEX commands

struct gpre_index
{
	gpre_sym* ind_symbol;		// index name
	gpre_rel* ind_relation;		// relation name
	gpre_fld* ind_fields;		// list of fields
	USHORT ind_flags;			// Miscellaneous flags
};

const size_t IND_LEN = sizeof(gpre_index);

enum ind_flags_vals {
	IND_dup_flag	= 1,	// if false, duplicates not allowed
//	IND_meta		= 2,	// if true, created for a metadata operation; set but not used
	IND_descend		= 4,	// if true, a descending-order index
	IND_active		= 8,	// activate index
	IND_inactive	= 16	// de-activate index
};


// Symbolic names for international text types
// (either collation or character set name)

// International symbol

struct intlsym
{
	gpre_dbb* intlsym_database;
	gpre_sym* intlsym_symbol;	// Hash symbol for intlsym
	intlsym* intlsym_next;
	USHORT intlsym_type;		// what type of name
	USHORT intlsym_flags;
	SSHORT intlsym_ttype;		// id of implementation
	SSHORT intlsym_charset_id;
	SSHORT intlsym_collate_id;
	USHORT intlsym_bytes_per_char;
	TEXT intlsym_name[2];
};

const size_t INTLSYM_LEN = sizeof(intlsym);

// values used in intlsym_type
enum intlsym_type_vals {
	INTLSYM_collation	= 1,
	INTLSYM_charset		= 2
};

// values used in intlsym_flags

// Field block.  Fields are what farms and databases are all about

struct gpre_fld
{
	USHORT fld_dtype;			// data type of field
	FLD_LENGTH fld_length;		// field length in bytes
	SSHORT fld_scale;			// scale factor
	USHORT fld_id;				// field id in meta data
	USHORT fld_flags;			// Misc flags
	USHORT fld_seg_length;		// Segment length for blobs
	USHORT fld_position;		// Field position in relation
	USHORT fld_precision;		// Field precision
	SSHORT fld_sub_type;		// Field sub-type
	gpre_fld* fld_next;			// next field in relation
	gpre_fld* fld_array;		// array element if field is array
	gpre_rel* fld_relation;		// relation
	gpre_prc* fld_procedure;	// procedure
	gpre_sym* fld_symbol;		// symbol for field
	gpre_sym* fld_global;		// symbol for global field
	ary* fld_array_info;		// Dimension and range information about an array field
	gpre_nod* fld_default_value;// field's default value
	gpre_txt* fld_default_source;	// source for field default value
	gpre_index* fld_index;		// If CREATE TABLE, specifies field with the unique constraint
	cnstrt* fld_constraints;	// linked list of constraints defined during a meta operation
	intlsym* fld_character_set; // character set for SQL declared field
	intlsym* fld_collate;		// collation clause for SQL declared field
	cmpf* fld_computed;			// computed field definition
	USHORT fld_char_length;		// field length in CHARACTERS
	SSHORT fld_charset_id;		// Field character set id for text
	SSHORT fld_collate_id;		// Field collation id for text
	SSHORT fld_ttype;			// ID of text type's implementation
};

const size_t FLD_LEN = sizeof(gpre_fld);

enum fld_flags_vals {
	FLD_blob		= 1,
	FLD_text		= 2,
	//FLD_stream_blob	= 4,	// unused
	FLD_dbkey		= 8,
	FLD_not_null	= 32,	// if CREATE TABLE specifies not null
	FLD_delete		= 64,	// if ALTER TABLE specifies delete of field
	FLD_meta		= 128,	// if true, created for a metadata operation
	FLD_national	= 256,	// uses SQL "NATIONAL" character set
	FLD_charset		= 512,	// field has a specific character set
	FLD_computed	= 1024,	// field is computed
	FLD_meta_cstring= 2048	// field is being defined as cstring by the user.
};


enum  fun_t {
	FUN_value,
	FUN_reference,
	FUN_descriptor,
	FUN_blob_struct,
	FUN_scalar_array
};


// Port block

struct gpre_port
{
	USHORT por_msg_number;		// message number within request
	ULONG por_ident;			// ident in source
	int por_length;				// length of port in bytes
	ref* por_references;		// linked list of field references
	gpre_port* por_next;		// next port in request
	USHORT por_count;			// number of items in port
};

const size_t POR_LEN = sizeof(gpre_port);


// Slice description block

struct slc
{
	gpre_req* slc_parent_request;	// request for blob id
	gpre_fld* slc_field;			// database array field
	gpre_nod* slc_array;			// user defined array
	ref* slc_field_ref;				// array field reference
	USHORT slc_dimensions;			// dimensions
	USHORT slc_parameters;			// number of parameters
	struct slc_repeat
	{
		gpre_nod* slc_lower;
		gpre_nod* slc_upper;
	} slc_rpt[1];
};

inline FB_SIZE_T SLC_LEN(const FB_SIZE_T count)
{
	return sizeof(slc) + sizeof(slc::slc_repeat) * (count ? count - 1 : 0);
}


// Request block, corresponds to a single JRD request

enum req_t {
	REQ_for,
	REQ_store,
	REQ_store2,
	REQ_insert,
	REQ_cursor,
	//REQ_select,		// unused
	REQ_mass_update,
	REQ_any,
	//REQ_statistical,	// unused
	REQ_ddl,
	REQ_create_database,
	REQ_slice,
	REQ_ready,
	REQ_procedure,
	REQ_set_generator,

	REQ_LASTREQUEST				// Leave this debugging gpre_req last
};

class gpre_req
{
public:

	req_t req_type;				// request type
	ULONG req_ident;			// ident for request handle
	//USHORT req_act_flag;		// activity flag ident, if used; unused
	int req_length;				// blr length of request
	UCHAR *req_base;			// base of blr string during generation
	UCHAR *req_blr;				// raw blr string
	SCHAR *req_handle;			// request handle
	const TEXT* req_trans;		// transaction handle
	const SCHAR* req_request_level;	// request level expression
	USHORT req_level;			// access level
	USHORT req_count;			// number of ports in request
	USHORT req_internal;		// next internal context number
	//USHORT req_labels;			// next available label; unused
#ifdef GPRE_FORTRAN
	USHORT req_top_label;		// fortran label for top of request
	USHORT req_btm_label;		// fortran label for request exit
#endif
	gpre_nod* req_node;			// request definition tree
	gpre_dbb* req_database;		// database
	act* req_actions;			// actions within request
	gpre_ctx* req_contexts;		// contexts within request
	gpre_ctx* req_update;		// update context for mass insert
	gpre_req* req_next;			// next request in module or metadata action
	ref* req_values;			// host values required
	ref* req_eof;				// eof reference for FOR
	//ref* req_index;				// index variable; unused
	ref* req_references;		// fields referenced in context
	map* req_map;				// map for aggregates, etc
	gpre_rse* req_rse;			// record selection expression
	gpre_port* req_ports;		// linked list of ports
	gpre_port* req_primary;		// primary input or output port
	gpre_port* req_sync;		// synchronization port
	gpre_port* req_vport;		// port to send values in
	gpre_req* req_routine;		// other requests in routine
	blb*		req_blobs;		// blobs in request
	slc* req_slice;				// slice for request
	ref* req_array_references;	// array fields referenced in context
	USHORT req_scope_level;		// scope level for SQL subquery parsing
	USHORT req_in_aggregate;	// now processing value expr for aggr
	USHORT req_in_select_list;	// processing select list
	USHORT req_in_where_clause;	// processing where clause
	USHORT req_in_having_clause;	// processing having clause
	USHORT req_in_order_by_clause;	// processing order by clause
	USHORT req_in_subselect;	// processing a subselect clause
	ULONG req_flags;

	inline void add_end()
	{
		*req_blr++ = isc_dyn_end;
	}
	inline void add_byte(const int byte)
	{
		*req_blr++ = (SCHAR) (byte);
	}
	inline void add_word(const int word)
	{
		add_byte(word);
		add_byte(word >> 8);
	}
	inline void add_long(const long lg)
	{
		add_word(lg);
		add_word(lg >> 16);
	}
	inline void add_cstring(const char* string)
	{
		add_byte(static_cast<int>(strlen(string)));
		UCHAR c;
		while ((c = *string++))
			add_byte(c);
	}

};

enum req_flags_vals {
	REQ_exp_hand			= 1,
	REQ_local				= 2,		// defined in an included routine
	REQ_sql_cursor			= 1024,		// request is an SQL cursor
	REQ_extend_dpb			= 2048,		// we need to extend dpb at runtime
	REQ_sql_declare_cursor	= 4096,		// request is declare cursor
	REQ_sql_blob_open		= 8192,		// request is SQL open blob cursor
	REQ_sql_blob_create		= 16384,	// request is SQL create blob cursor
	REQ_sql_database_dyn	= 32768,	// request is to generate DYN to add files o database
	REQ_blr_version4		= 65536,	// request must generate blr_version4
	REQ_sql_returning		= 131072	// RETURNING clause is present
};

const size_t REQ_LEN = sizeof(gpre_req);


// Context block, used to define context symbols, etc.

struct gpre_ctx {
	USHORT ctx_internal;		// internal context number
	USHORT ctx_scope_level;		// scope level for SQL alias subquery scoping
	gpre_req* ctx_request;		// parent request
	gpre_ctx* ctx_next;			// next context in request
	gpre_sym* ctx_symbol;		// symbol for context
	gpre_rel* ctx_relation;		// relation for context
	TEXT *ctx_alias;			// holds SQL alias for passing to engine
	gpre_prc* ctx_procedure;	// procedure for context
	gpre_nod* ctx_prc_inputs;	// procedure input parameters
	gpre_rse* ctx_stream;		// stream for context
	USHORT ctx_flags;			// misc flags
};

enum ctx_flags_vals {
	CTX_null = 1				// context evaluates to NULL
};

const size_t CTX_LEN = sizeof(gpre_ctx);


// Field reference

class ref
{
public:

	USHORT ref_ident;			// identifier
	USHORT ref_level;			// highest level of access
	USHORT ref_parameter;		// parameter in port
	USHORT ref_id;				// id of reference in union
	gpre_fld* ref_field;		// field in question
	gpre_ctx* ref_context;		// context for reference
	ref* ref_next;				// next reference in context
	gpre_port* ref_port;		// associated port
	ref* ref_source;			// source reference for modified field
	ref* ref_null;				// reference for null value
	ref* ref_master;			// master field for null value
	ref* ref_friend;			// value for variable
	gpre_nod* ref_expr;			// expression, if node is expression
	const TEXT* ref_value;		// value string if host language value
	gpre_value* ref_values;		// linked list of values
	const TEXT* ref_null_value;	// value string if host language value
	UCHAR* ref_sdl;				// Raw slice description language for an array
	UCHAR* ref_sdl_base;		// base of sdl string during generation
	int ref_sdl_length;			// sdl length for this reference
	slc* ref_slice;				// Slice, if field referenced is sliced
	ULONG ref_sdl_ident;		// identifier of sdl structure
#ifdef GPRE_FORTRAN
	USHORT ref_offset;			// offset of field in port
#endif
	USHORT ref_flags;
	SSHORT ref_ttype;			// Character set type for literals

	inline void add_byte(const int byte)
	{
		*ref_sdl++ = (UCHAR) byte;
	}
	inline void add_word(const int word)
	{
		add_byte(word);
		add_byte(word >> 8);
	}
	inline void add_long(const long lg)
	{
		add_word(lg);
		add_word(lg >> 16);
	}

};

enum ref_flags_vals {
	//REF_union		= 1,	// Pseudo field for union, never set
	//REF_pseudo		= 2,	// Other pseudo field (probably for forms), unused
	REF_null		= 4,	// Only here cause of related null reference
	REF_fetch_array	= 8,	// Need to fetch full array
	REF_literal		= 16,	// Reference is to a constant
	REF_ttype		= 32,	// Reference contains character set spec
	REF_array_elem	= 64,	// Reference to an array element
	REF_sql_date	= 128,	// Reference is to a date constant
	REF_sql_time	= 256,	// Reference is to a time constant
	REF_timestamp	= 512	// Reference is to a timestamp constant
};

const size_t REF_LEN = sizeof(ref);


// *************** start of tree roots ****************

// Based on block.  Used for based on clause

struct bas
{
	gpre_fld* bas_field;		// database field referenced
	gpre_lls* bas_variables;	// list of variables based on above
	str* bas_db_name;			// database name if present and required
	str* bas_rel_name;			// relation name if no db statement
	str* bas_fld_name;			// field if no db statement
	USHORT bas_flags;
	char bas_terminator[2];		// terminating character
};

const size_t BAS_LEN = sizeof(bas);

enum bas_flags_vals {
	BAS_segment		= 1,		// Based on a blob segment length
	BAS_ambiguous	= 2			// Ambiguous reference to segment
};


// declare udf block

struct decl_udf
{
	const TEXT *decl_udf_name;
	const TEXT *decl_udf_entry_point;
	const TEXT *decl_udf_module_name;
	gpre_fld* decl_udf_arg_list;
	gpre_fld* decl_udf_return_type;
	USHORT decl_udf_return_mode;	// BY VALUE or BY REFERENCE
	SSHORT decl_udf_return_parameter;
};


const size_t DECL_UDF_LEN = sizeof(decl_udf);


// Dynamic statement block, used for dynamic SQL

struct dyn
{
	gpre_dbb* dyn_database;			// Database involved
	gpre_sym* dyn_statement_name;	// Name of dynamic statement
	gpre_sym* dyn_cursor_name;		// Cursor name
	const TEXT* dyn_trans;			// Transaction handle
	TEXT *dyn_string;			// Dynamic string or variable name
	TEXT *dyn_sqlda;			// Name of SQLDA structure, if any
	TEXT *dyn_sqlda2;			// Name of second SQLDA structure, if any
	gpre_nod* dyn_using;		// dependent on action type
};

const size_t DYN_LEN = sizeof(dyn);


// Start transaction block

struct gpre_tra {
	gpre_tra* tra_next;			// next transaction
	TEXT *tra_handle;			// this handle
	USHORT tra_flags;			// transaction options
	tpb* tra_tpb;				// TPB's for this transaction
	int tra_db_count;			// number of db's and TPB's
};

const size_t TRA_LEN = sizeof(gpre_tra);


// values for tra_flags
enum tra_flags_vals {
	TRA_ro				= 1,
	TRA_nw				= 2,
	TRA_con				= 4,
	TRA_rrl 			= 8,
	TRA_inc 			= 16,
	TRA_read_committed	= 32,
	TRA_autocommit		= 64,
	TRA_rec_version		= 128,
	TRA_no_auto_undo	= 256
};

const int MAX_TRA_OPTIONS	= 8;


// act_object block for SQL database commands.

struct mdbb {
	gpre_dbb* mdbb_database;
	gpre_req* mdbb_dpb_request;
	//gpre_req* mdbb_dpb_extend_request;	// unused
};


// Open cursor block

struct open_cursor {
	gpre_sym* opn_cursor;		// Symbol block of cursor
	const TEXT* opn_trans;		// Transaction handle
	ref* opn_using;				// Using variables
};

const size_t OPN_LEN = sizeof(open_cursor);


// Ready block

struct rdy {
	gpre_req* rdy_request;		// dpb message & info
	rdy* rdy_next;
	gpre_dbb* rdy_database;
#ifdef GPRE_COBOL
	USHORT rdy_id;				// id for unique string variable- MPEXL COB
#endif
	TEXT *rdy_filename;
};

const size_t RDY_LEN = sizeof(rdy);


// Enumerated field type block

struct field_type {
	gpre_sym* typ_symbol;		// Actual symbol, set but never used
	gpre_fld* typ_field;		// Owner
	SSHORT typ_value;			// Value of type
};

const size_t TYP_LEN = sizeof(field_type);


// User Defined Function

struct udf {
	gpre_dbb* udf_database;
	gpre_sym* udf_symbol;		// Function name or query name
	USHORT udf_args;			// Number of arguments
	USHORT udf_flags;			// udf flags
	USHORT udf_dtype;			// Return data type
	SSHORT udf_scale;			// Return scale
	USHORT udf_length;			// Return length
	USHORT udf_sub_type;		// Return sub-type
	USHORT udf_charset_id;		// Return character set
	USHORT udf_ttype;			// Return text type
	USHORT udf_type;			// Function type
	gpre_fld* udf_inputs;		// List of udf input arguments
	TEXT udf_function[1];		// Function name
};

const size_t UDF_LEN = sizeof(udf);

enum udf_type_vals {
	UDF_value,
	UDF_boolean
};

enum udf_flags_vals {
	UDF_scanned = 1
};


// Update block -- used for (at least) MODIFY

struct upd {
	USHORT upd_level;			// reference level
	gpre_req* upd_request;		// parent request
	ref* upd_references;		// references under modify
	gpre_ctx* upd_source;		// context being modified
	gpre_ctx* upd_update;		// update context
	gpre_port* upd_port;		// port for update
	//upd* upd_outer;				// outer modify, if any; unused
	gpre_nod* upd_assignments;	// assignments to port
	//ref* upd_array_references;	// array references under modify; unused
};

const size_t UPD_LEN = sizeof(upd);

#include "../common/dsc.h"
#include "parse.h"

// GPRE wide globals

struct GpreGlobals
{
	bool sw_auto;
	bool sw_sql;
	bool sw_raw;
	bool sw_cstring;
	bool sw_dyn_using;
	bool sw_ids;
	bool sw_case;
	bool sw_external;
	bool sw_version;
	bool sw_d_float;
	bool sw_no_qli;
	USHORT sw_sql_dialect;
	bool sw_know_interp;
	USHORT sw_server_version;
	USHORT sw_ods_version;
	bool override_case;
	bool dialect_specified;
	bool trusted_auth;

	SSHORT sw_interp;
	USHORT compiletime_db_dialect;

	gpre_dbb* isc_databases;
	const TEXT* default_user;
	const TEXT* default_password;
	const TEXT* default_lc_ctype;
	gpre_req* requests;
	gpre_lls* events;
	FILE *out_file;
	lang_t sw_language;
	int errors_global;
	act* global_functions;
	intlsym* text_subtypes;

#ifdef GPRE_ADA
	TEXT ada_package[MAXPATHLEN];
	const TEXT* ada_null_address;
	// ada_flags fields definition
	int ADA_create_database;	// the flag is set when there is a
								// create database SQL statement in
								// user program, and is used to
								// generate additional "with" and
								// "function" declarations
	USHORT ada_flags;
#endif

#ifdef GPRE_COBOL
	cob_t sw_cob_dialect;
	const TEXT* sw_cob_dformat;
#endif

#ifdef GPRE_FORTRAN
	// from gpre.cpp
	UCHAR fortran_labels[1024];
	dbd global_db_list[MAX_DATABASES];
	USHORT global_db_count;
#endif

	const TEXT* ident_pattern;
	const TEXT* long_ident_pattern;
	const TEXT* utility_name;
	const TEXT* count_name;
	const TEXT* slack_name;
	const TEXT* transaction_name;
	const TEXT* database_name;
	tok prior_token;
	// from par.cpp
	act* cur_routine;
	// from sql.cpp
	const TEXT* module_lc_ctype;
	// from parse.h
	tok token_global;
};

extern GpreGlobals gpreGlob;


#ifndef fb_assert
#ifdef DEV_BUILD
#undef fb_assert
#define fb_assert(ex)	{if (!(ex)) {CPR_assert (__FILE__, __LINE__);}}
#else // DEV_BUILD
#undef fb_assert
#define fb_assert(ex)
#endif // DEV_BUILD
#endif // fb_assert

#define assert_IS_REQ(x) fb_assert(!(x) || ((x)->req_type >= 0 && (x)->req_type < REQ_LASTREQUEST))
//#define assert_IS_SYM(x) fb_assert(!(x) || ((x)->sym_type >= 0 && (x)->sym_type < SYM_LASTSYM))
#define assert_IS_NOD(x) fb_assert(!(x) || ((x)->nod_type >= 1 && (x)->nod_type < nod_LASTNOD))
//#define assert_IS_ACT(x) fb_assert(!(x) || ((x)->act_type >= 0 && (x)->act_type < ACT_LASTACT))


class gpre_exception: public Firebird::LongJump
{
	char msg[MAXPATHLEN << 1];
public:
	gpre_exception()
	{
		msg[0] = 0;
	}
	gpre_exception(const char* errmsg)
	{
		fb_utils::copy_terminate(msg, errmsg, sizeof(msg));
	}
	const char* what() const noexcept
	{
		return msg[0] ? msg : "gpre_exception";
	}
};

#endif // GPRE_GPRE_H

